package com.multipledatasource.config;

import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.jdbc.DataSourceBuilder;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.core.env.Environment;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;

import javax.sql.DataSource;
import java.util.HashMap;
import java.util.Map;

/**
 * 创建数据源
 */
@Configuration
@MapperScan(basePackages = "com.multipledatasource.web.mapper")//扫描包路径下的mapper
public class DataSourceConfig {

    /**
     * 读取yml或者properties配置文件
     */
    @Autowired
    private Environment env;

    /**
     * 配置数据源
     * @return
     */
    //用户
    @Bean(name = "dataSourceUser")//指定名称，未指定默认为方法名
    @ConfigurationProperties(prefix = "spring.datasource.user")//prefix对应yml中的前缀
    public DataSource dataSourceUser(){
        return DataSourceBuilder.create().build();
    }
    //商品
    @Bean(name = "dataSourceGoods")
    @ConfigurationProperties(prefix = "spring.datasource.goods")
    public DataSource dataSourceGoods(){
        return DataSourceBuilder.create().build();
    }
    //订单
    @Bean(name = "dataSourceOrder")
    @ConfigurationProperties(prefix = "spring.datasource.order")
    public DataSource dataSourceOrder(){
        return DataSourceBuilder.create().build();
    }

    /**
     * 动态切换数据源类
     * @Primary 指定默认数据源
     * @param user
     * @param goods
     * @param order
     * @return
     */
    @Primary //指定默认数据源，此处为第一个是dataSourceUser
    @Bean("dataSource")
    public DynamicDataSource dataSource(@Qualifier("dataSourceUser") DataSource user,
                                        @Qualifier("dataSourceGoods") DataSource goods,
                                        @Qualifier("dataSourceOrder") DataSource order) {
        DynamicDataSource dynamicDataSource = new DynamicDataSource();
        Map targetDataSources = new HashMap<>();
        targetDataSources.put(DataSourceEnum.USER, user);
        targetDataSources.put(DataSourceEnum.GOODS, goods);
        targetDataSources.put(DataSourceEnum.ORDER, order);
        dynamicDataSource.setTargetDataSources(targetDataSources);
        // 设置默认的数据源
        dynamicDataSource.setDefaultTargetDataSource(user);
        return dynamicDataSource;

    }

    /**
     * 根据动态数据源配置，创建sqlSessionFactory
     * @param user
     * @param goods
     * @param order
     * @return
     * @throws Exception
     */
    @Primary
    @Bean("sqlSessionFactory")
    public SqlSessionFactory sqlSessionFactory(@Qualifier("dataSourceUser") DataSource user,
                                               @Qualifier("dataSourceGoods") DataSource goods,
                                               @Qualifier("dataSourceOrder") DataSource order) throws Exception {
        SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
        sessionFactory.setDataSource(this.dataSource(user, goods,order));
        sessionFactory.setTypeAliasesPackage(env.getProperty("mybatis.type-aliases-package"));//对应yml中mybatis的bean目录
        sessionFactory.setMapperLocations(new PathMatchingResourcePatternResolver().getResources(env.getProperty("mybatis.mapper-locations")));//对应yml中mybatis的xml
        return sessionFactory.getObject();

    }


    /**
     * 根据动态数据源配置，创建transactionManager
     * @param dataSource
     * @return
     * @throws Exception
     */
    @Bean("transactionManager")
    public DataSourceTransactionManager transactionManager(@Qualifier("dataSource") DynamicDataSource dataSource) throws Exception {
        return new DataSourceTransactionManager(dataSource);
    }


}
